/*
 * Copyright 2011 Fabian Wenzelmann
 * 
 * This file is part of Recognition-Procedures-for-Boolean-Functions.
 * 
 * Recognition-Procedures-for-Boolean-Functions is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Recognition-Procedures-for-Boolean-Functions is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Recognition-Procedures-for-Boolean-Functions.  If not, see <http://www.gnu.org/licenses/>.
 */

package de.wenzelmf.booleanFunction.lpb.util;

import java.io.Serializable;

import de.wenzelmf.booleanFunction.dnf.Literal;

/**
 * This class represents a single summand on the left-hand side of an LPB, namely a pair a<sub>i</sub> &middot; l<sub>i</sub>
 * where a<sub>i</sub> is the <i>coefficient</i> and l<sub>i</sub> is a Literal (either x<sub>i</sub>
 * for positive occurrence or (1 - x<sub>i</sub>) for a negative occurrence of x<sub>i</sub>).
 * 
 * @author Fabian Wenzelmann
 * @version 1.0
 *
 */
public class LPBSummand implements Serializable
{
	// TODO: allow only positive coefficients?
	private static final long serialVersionUID = 7925993802407994942L;
	
	/*
	 * Literal this summand is associated with.
	 */
	private Literal literal;
	
	/*
	 * The coefficient of this summand.
	 */
	private int coefficient;
	
	/**
	 * Creates a new summand a<sub>i</sub> &middot; l<sub>i</sub>.
	 * 
	 * @param literal The literal that is associated with this summand, namely l<sub>i</sub>.
	 * @param coefficient The coefficient that is associated with this summand, namely a<sub>i</sub>.
	 */
	public LPBSummand(Literal literal, int coefficient)
	{
		this.literal = literal;
		this.coefficient = coefficient;
	}
	
	/**
	 * Creates a new summand a<sub>i</sub> &middot; l<sub>i</sub> where l<sub>i</sub> = x<sub>i</sub>
	 * (positive occurrence) and the identifier of x<sub>i</sub> is the {@code identifier}.
	 * 
	 * @param identifier identifier of the variable.
	 * @param coefficient The coefficient that is associated with this summand, namely a<sub>i</sub>.
	 */
	public LPBSummand(String identifier, int coefficient)
	{
		this(new Literal(identifier), coefficient);
	}
	
	/**
	 * Returns the identifier of the associated literal.
	 * 
	 * @return Identifier of {@code this.literal}.
	 */
	public String getIdentifier()
	{
		return literal.getIdentifier();
	}
	
	/**
	 * Returns the literal that is associated with this summand (l<sub>i</sub>).
	 * @return l<sub>i</sub>.
	 */
	public Literal getLiteral()
	{
		return literal;
	}
	
	/**
	 * Returns the coefficient that is associated with this summand (the value a<sub>i</sub>).
	 * @return a<sub>i</sub>.
	 */
	public int getCoefficient()
	{
		return coefficient;
	}
	
	/**
	 * Returns {@code true} if the occurrence of x<sub>i</sub> is positive and {@code false} otherwise.
	 *
	 * @return {@code true} if x<sub>i</sub> occurrs positive.
	 */
	public boolean isPositive()
	{
		return literal.isPositive();
	}
	
	/**
	 * Returns a string representation of this summand.
	 * 
	 * @return {@code "this.literal.identifier"} if x<sub>i</sub> occurrs positive
	 * and {@code "(1 - this.literal.identifier)"} otherwise. 
	 */
	@Override
	public String toString()
	{
		if(isPositive())
		{
			return getCoefficient() + " " + getIdentifier();
		}
		else
		{
			return getCoefficient() + " " + "(1 - " + getIdentifier() + ")";
		}
	}
	
	/**
	 * Tests if two LPBSummands are equal (same literal and same coefficient).
	 * 
	 * More formal: a<sub>i</sub>l<sub>i</sub> = a<sub>j</sub>l<sub>j</sub> iff a<sub>i</sub> = a<sub>j</sub>
	 * and l<sub>i</sub> &equiv; l<sub>j</sub>. 
	 * 
	 * @return {@code true} if other is also an LPBSummand and equal to this (same coefficient and literal).
	 */
	@Override
	public boolean equals(Object other)
	{
		if(!(other instanceof LPBSummand))
			return false;
		LPBSummand otherSummand = (LPBSummand)other;
		return getCoefficient() == otherSummand.getCoefficient() && getLiteral().equals(otherSummand.getLiteral());
	}
	
	/**
	 * Returns a hash value representing this object (literal hashCode + coefficient).
	 * 
	 * @return {@code this.literal.hashCode() + this.coefficient}.
	 */
	@Override
	public int hashCode()
	{
		return this.literal.hashCode() + coefficient;
	}
}
